﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "GcmpDatabase.h"
#include "GbmpCommon.h"
#include "GbmpAssert.h"
#include "ClassId.h"
#include "NdbPropertySchemaType.h"

namespace gcmp
{
    // 属性变化的种类。
    enum EnPropertyChangeType
    {
        CPCT_INVALID            = -1,   // 不合法的类型

        // 以下是有效的属性改变类型
        CPCT_ADD                = 0,    // 新增
        CPCT_DELETE             = 1,    // 删除
        CPCT_RENAME             = 2,    // 重命名
        CPCT_MOVE_FROM_ANCESTOR = 3,    // 从祖先类移动过来
        CPCT_MOVE_TO_ANCESTOR   = 4,    // 移到祖先类去
        CPCT_RETYPE             = 5,    // 重定义类型
        CPCT_COUNT              = 6,    // 有效类型的数量
        // 以上是有效的属性改变类型
    };

    class NdbPropertyChangeBase
    {
        DEFINE_CAST_BASE(gcmp::NdbPropertyChangeBase)
    protected:
        EnPropertyChangeType m_type;
    public:
        NdbPropertyChangeBase(EnPropertyChangeType changeType) : m_type(changeType) {}
        virtual ~NdbPropertyChangeBase() = 0;

        EnPropertyChangeType GetChangeType() const { return m_type; }
    };
    inline NdbPropertyChangeBase::~NdbPropertyChangeBase(){}

    class NdbAddPropertyChange : public NdbPropertyChangeBase
    {
        DEFINE_CAST_DERIVED(gcmp::NdbAddPropertyChange, gcmp::NdbPropertyChangeBase)
    public:
        NdbAddPropertyChange(
            const std::wstring& propertyName,
            const ClassId & propertyClassId,
            const ClassId & classId,
            NdbPropertySchemaType schemaType,
            UInt32 propertySize
        ) 
            : NdbPropertyChangeBase(CPCT_ADD)
            , m_propertyName(propertyName)
            , m_propertyClassId(propertyClassId)
            , m_classId(classId)
            , m_schemaType(schemaType)
            , m_propertySize(propertySize)
            , m_intOrFloatType(IntOrFloatType::UnKnown)
            , m_intBaseType(IntBaseType::UnKnown)
        {}

        const std::wstring& GetPropertyName() const { return m_propertyName; }
        const ClassId & GetPropertyClassId() const { return m_propertyClassId; }
        const ClassId & GetClassId() const { return m_classId; }
        NdbPropertySchemaType GetSchemaType() const { return m_schemaType; }
        UInt32 GetPropertySize() const { return m_propertySize; }
        IntOrFloatType GetIntOrFloatType() const { return m_intOrFloatType; }
        void SetIntOrFloatType(IntOrFloatType en)  { m_intOrFloatType = en; }
        IntBaseType GetIntBaseType() const { return m_intBaseType; }
        void SetIntBaseType(IntBaseType base)  { m_intBaseType = base; }

    private:
        std::wstring m_propertyName;
        ClassId m_propertyClassId;
        ClassId m_classId;
        NdbPropertySchemaType m_schemaType;
        UInt32 m_propertySize;
        IntOrFloatType m_intOrFloatType;
        IntBaseType m_intBaseType;
    };

    class NdbDeletePropertyChange : public NdbPropertyChangeBase
    {
        DEFINE_CAST_DERIVED(gcmp::NdbDeletePropertyChange, gcmp::NdbPropertyChangeBase)
    private:
        std::wstring m_propertyName;
    public:
        NdbDeletePropertyChange(const std::wstring& propertyName)
            : NdbPropertyChangeBase(CPCT_DELETE)
            , m_propertyName(propertyName)
        {}

        const std::wstring& GetPropertyName() const { return m_propertyName; }
    };

    class NdbRenamePropertyChange : public NdbPropertyChangeBase
    {
        DEFINE_CAST_DERIVED(gcmp::NdbRenamePropertyChange, gcmp::NdbPropertyChangeBase)
    private:
        std::wstring m_oldPropertyName;
        std::wstring m_newPropertyName;
    public:
        NdbRenamePropertyChange(const std::wstring& oldPropertyName, const std::wstring& newPropertyName)
            : NdbPropertyChangeBase(CPCT_RENAME)
            , m_oldPropertyName(oldPropertyName)
            , m_newPropertyName(newPropertyName)
        {}

        const std::wstring& GetOldPropertyName() const { return m_oldPropertyName; }
        const std::wstring& GetNewPropertyName() const { return m_newPropertyName; }
    };

    class NdbRetypePropertyChange : public NdbPropertyChangeBase
    {
        DEFINE_CAST_DERIVED(gcmp::NdbRetypePropertyChange, gcmp::NdbPropertyChangeBase)
    private:
        std::wstring            m_propertyName;

        std::wstring            m_oldTypeName;
        UInt32                  m_oldPropertySize;
        std::wstring            m_newTypeName;
        UInt32                  m_newPropertySize;

        IntOrFloatType m_newIntOrFloatType;
        IntBaseType m_newIntBaseType;
    public:
        NdbRetypePropertyChange(
            const std::wstring& propertyName,
            const std::wstring& oldTypeName,
            UInt32 oldPropertySize,
            const std::wstring& newTypeName,
            UInt32 newPropertySize
        )
            : NdbPropertyChangeBase(CPCT_RETYPE)
            , m_propertyName(propertyName)
            , m_oldTypeName(oldTypeName)
            , m_oldPropertySize(oldPropertySize)
            , m_newTypeName(newTypeName)
            , m_newPropertySize(newPropertySize)
            , m_newIntOrFloatType(IntOrFloatType::UnKnown)
            , m_newIntBaseType(IntBaseType::UnKnown)
        {}

        const std::wstring& GetPropertyName() const { return m_propertyName; }
        const std::wstring& GetOldTypeName() const { return m_oldTypeName; }
        UInt32 GetOldPropertySize() const { return m_oldPropertySize; }
        const std::wstring& GetNewTypeName() const { return m_newTypeName; }
        UInt32 GetNewPropertySize() const { return m_newPropertySize; }

        IntOrFloatType GetNewIntOrFloatType() const { return m_newIntOrFloatType; }
        void SetNewIntOrFloatType(IntOrFloatType intOrFloatType) { m_newIntOrFloatType = intOrFloatType; }
        IntBaseType GetNewIntBaseType() const { return m_newIntBaseType; }
        void SetNewIntBaseType(IntBaseType intBaseType) { m_newIntBaseType = intBaseType; }
    };

    class NdbExchangePropertyWithAncestorChange : public NdbPropertyChangeBase
    {
        DEFINE_CAST_DERIVED(gcmp::NdbExchangePropertyWithAncestorChange, gcmp::NdbPropertyChangeBase)
    private:
        // m_ancestorClassName仅辅助报错和调试，作为索引的是m_ancestorClassId
        std::wstring m_ancestorClassName;
        ClassId      m_ancestorClassId;
        std::wstring m_oldPropertyName;
        std::wstring m_newPropertyName;
    public:
        NdbExchangePropertyWithAncestorChange(
            EnPropertyChangeType changeType,
            const std::wstring& ancestorClassName,
            const ClassId & ancestorClassId,
            const std::wstring& oldPropertyName,
            const std::wstring& newPropertyName
        ) 
            : NdbPropertyChangeBase(changeType)
            , m_ancestorClassName(ancestorClassName)
            , m_ancestorClassId(ancestorClassId)
            , m_oldPropertyName(oldPropertyName)
            , m_newPropertyName(newPropertyName)
        {
            DBG_CRASH(changeType == CPCT_MOVE_FROM_ANCESTOR || changeType == CPCT_MOVE_TO_ANCESTOR, L"changeType should only be CPCT_MOVE_FROM_ANCESTOR or CPCT_MOVE_TO_ANCESTOR");
        }

        const std::wstring& GetAncestorClassName() const { return m_ancestorClassName; }
        const ClassId & GetAncestorClassId() const { return m_ancestorClassId; }
        const std::wstring& GetOldPropertyName() const { return m_oldPropertyName; }
        const std::wstring& GetNewPropertyName() const { return m_newPropertyName; }
    };

    class NdbParentClassChange
    {
    public:
        NdbParentClassChange(
            const std::wstring& srcClassName,
            const ClassId & srcClassId,
            const std::wstring& dstClassName,
            const ClassId & dstClassId
        )
            : m_srcClassName(srcClassName)
            , m_srcClassId(srcClassId)
            , m_dstClassName(dstClassName)
            , m_dstClassId(dstClassId)
        {}

        const std::wstring& GetSrcClassName() const { return m_srcClassName; }
        const ClassId & GetSrcClassId() const { return m_srcClassId; }

        const std::wstring& GetDstClassName() const { return m_dstClassName; }
        const ClassId & GetDstClassId() const { return m_dstClassId; }

    private:
        // m_srcClassName辅助报错和调试，作为索引的是m_srcClassId
        std::wstring m_srcClassName;
        ClassId   m_srcClassId;
        // m_dstClassName辅助报错和调试，作为索引的是m_dstClassId
        std::wstring m_dstClassName;
        ClassId   m_dstClassId;
    };
}

